1 module hip.gui.scroll_area; 2 import hip.gui.widget; 3 import hip.gui.button; 4 5 6 interface IRawScrollable 7 { 8 void onRawScroll(float[3] scroll); 9 } 10 11 class ScrollArea : Widget, IRawScrollable 12 { 13 private static IWidgetRenderer DebugRenderer() 14 { 15 import hip.api.graphics.g2d.renderer2d; 16 __gshared DebugWidgetRenderer dbgRenderer; 17 if(dbgRenderer is null) dbgRenderer = new DebugWidgetRenderer(HipColor(85,85,85,85)); 18 return dbgRenderer; 19 } 20 private IWidgetRenderer renderer; 21 private float scrollRate = -10, currentScroll = 0, lastScroll = 0; 22 23 this(int width, int height) 24 { 25 this.width = width; 26 this.height = height; 27 renderer = DebugRenderer(); 28 } 29 30 override Bounds getWorldBounds(){return Bounds(worldTransform.x, worldTransform.y, width, height);} 31 void setRenderer(IWidgetRenderer renderer) 32 { 33 assert(renderer !is null); 34 this.renderer = renderer; 35 } 36 37 void setScrollRate(float rate) 38 { 39 this.scrollRate = rate; 40 } 41 42 void setScroll(float scroll) 43 { 44 lastScroll = currentScroll; 45 currentScroll = scroll; 46 foreach(ch; children) 47 ch.onScroll([0,currentScroll,0], [0,lastScroll,0]); 48 } 49 50 void onRawScroll(float[3] scroll) 51 { 52 import hip.api; 53 setScroll(currentScroll + scroll[1]*scrollRate); 54 } 55 56 override void onRender() 57 { 58 import hip.api.graphics.g2d.renderer2d; 59 60 setStencilTestingEnabled(true); 61 setStencilTestingFunction(HipStencilTestingFunction.Always, 1, 0xFF); 62 setStencilOperation(HipStencilOperation.Keep, HipStencilOperation.Keep, HipStencilOperation.Replace); 63 setRendererColorMask(0,0,0,0); 64 fillRectangle(worldTransform.x, worldTransform.y, width, height); 65 setRendererColorMask(1,1,1,1); 66 setStencilTestingFunction(HipStencilTestingFunction.Equal, 1, 0xFF); 67 renderer.render(worldTransform.x, worldTransform.y, width, height); 68 foreach(ch; children) 69 ch.render(); 70 71 setStencilTestingEnabled(false); 72 } 73 } 74 75 import hip.gui.linear_layout; 76 import hip.gui.group; 77 class ScrollBar : LinearLayout 78 { 79 private 80 { 81 Button backward; 82 Button thumb; 83 Button forward; 84 } 85 86 ///Used to keep the layout size fixed 87 private Widget thumbFixer; 88 private int barSize = 50; 89 private int barRate = 1; 90 private float barScale = 1; 91 private int[2] buttonsDimensions; 92 93 void setButtonsSize(int width, int height) 94 { 95 forward.width = backward.width = width; 96 forward.height = backward.height = height; 97 } 98 99 void setBarSize(int size) 100 { 101 barSize = size; 102 setDimensionFromDirection(size); 103 } 104 105 void setTarget(int* target) 106 { 107 backward.setOnClick((){*target = *target - barRate;}); 108 forward.setOnClick((){*target = *target + barRate;}); 109 } 110 111 private void setDimensionFromDirection(int dimensionSize) 112 { 113 if(dir == LinearLayout.Direction.horizontal) 114 { 115 thumb.width = cast(int)(dimensionSize * barScale); 116 thumbFixer.width = dimensionSize; 117 } 118 else 119 { 120 thumb.height = cast(int)(dimensionSize * barScale); 121 thumbFixer.height = dimensionSize; 122 } 123 } 124 125 void setBarScale(int itemsShowing, int itemsCount) 126 { 127 barScale = cast(float)itemsShowing / itemsCount; 128 setDimensionFromDirection(this.barSize); 129 } 130 131 this(LinearLayout.Direction direction) 132 { 133 setDirection(direction); 134 thumbFixer = new Group(); 135 thumbFixer.addChild(thumb = new Button(0,0, 50, 50)); 136 backward = new Button(0,0, 50, 50); 137 forward = new Button(0,0, 50, 50); 138 139 addChild(backward, thumbFixer, forward); 140 } 141 }